/****************************************************************************

	COPYRIGHT(C) MAXSI SOFTWARE, JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010

    This file is part of Maxsi Distribution.

    Maxsi Distribution is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maxsi Distribution is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Maxsi Distribution. If not, see <http://www.gnu.org/licenses/>.

	*/ #include "MaxsiDistributionContributors.h" /*

	If you modify this file, please enter your name below and provide contact
	information in MaxsiDistributionContributors.h. For more information please see
	MaxsiDistributionContributors.h.
	
	Contributors to this file:

	- Jonas 'Sortie' Termansen
	- [your name here]

	MaxsiDistribution.dll
	Distributing since 2008

	MaxsiDistributionInterface001.cpp
	An interface to the Maxsi Distribution Platform.

****************************************************************************/

#include "MaxsiEngine.h"
#include "MaxsiDistributionLink.h"
#include "Data.h"
#include "Thread.h"
#include "Interface.h"
#include "Interfaces.h"

//=============================================================================
//	Make sure we can easily copy paste code from this file to newer interfaces
//	without having to change too much code.
//=============================================================================
extern MaxsiDistributionClass001*	SDKCallback001;

// Maxsi Distribution Module
#ifdef MaxsiDistributionModule
#undef MaxsiDistributionModule
#endif
#define MaxsiDistributionModule MaxsiDistributionModule001

// Maxsi Distribution Interface
#ifdef MaxsiDistributionInterface
#undef MaxsiDistributionInterface
#endif
#define MaxsiDistributionInterface MaxsiDistributionInterface001

// Maxsi Distribution SDK Callback
#ifdef SDKCallback
#undef SDKCallback
#endif
#define SDKCallback SDKCallback001

//=============================================================================
//	Define all the GetInterface functions we need!
//=============================================================================

MD_DECLARE_INTERFACE(MaxsiDistributionInterface, "MaxsiDistributionInterface001");

MaxsiDistributionInterface::MaxsiDistributionInterface()
{
	m_Initialized			=	false;
	m_IsEnabled				=	true;
}

MaxsiDistributionInterface::~MaxsiDistributionInterface()
{

}

//=============================================================================
//	bool	Initialize(char** Variables, size_t NumVariables)
//
//	Sets a series of variables inside Maxsi Distribution.
//=============================================================================

bool	MaxsiDistributionInterface::Initialize(char** Variables, size_t NumVariables)
{
	IsIngame		=	true;
	IsInstall		=	false;
	IsUpdate		=	true;

	for (size_t I = 0; I < NumVariables*2; I+=2)
	{
		if ( _stricmp(Variables[I],"ContentType") == 0 )
		{
			if ( _stricmp(Variables[I+1],"Steam/SourceMod") == 0 )
			{
				MapPack		=	false;
			}
			else if ( _stricmp(Variables[I+1],"Steam/SourceMapPack") == 0 )
			{
				MapPack		=	true;
			}
		}
		else if ( _stricmp(Variables[I],"MDPath") == 0 )
		{

		}
		else if ( _stricmp(Variables[I],"MDRoot") == 0 )
		{
			if ( MDRoot) { delete[] MDRoot; } MDRoot = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"MDSeekPath") == 0 )
		{
			if ( MDSeekPath) { delete[] MDSeekPath; } MDSeekPath = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"MDDistribution") == 0 )
		{
			if ( MDDistribution) { delete[] MDDistribution; } MDDistribution = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"MDBinFolder") == 0 )
		{
			if ( MDBinFolder) { delete[] MDBinFolder; } MDBinFolder = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"MDBinary") == 0 )
		{

		}
		else if ( _stricmp(Variables[I],"ProductBin") == 0 )
		{

		}
		else if ( _stricmp(Variables[I],"ProductDirectory") == 0 )
		{

		}
		else if ( _stricmp(Variables[I],"ProductMasterServer") == 0 )
		{
			if ( MasterServer ) { delete[] MasterServer; } MasterServer = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"ProductName") == 0 )
		{
			if ( ProductName ) { delete[] ProductName; } ProductName = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"ProductPID") == 0 )
		{
			ProductPID	=	(DWORD)atoi(Variables[I+1]);		
		}
		else if ( _stricmp(Variables[I],"ProductRestartCmd") == 0 )
		{
			if ( OnCompleted ) { delete[] OnCompleted; } OnCompleted = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"ProductRoot") == 0 )
		{
			if ( SourceModPath ) { delete[] SourceModPath; } SourceModPath = BuildString(1,Variables[I+1]);
			if ( InstallPath ) { delete[] InstallPath; } InstallPath = BuildString(2,Variables[I+1],"../../");
		}
		else if ( _stricmp(Variables[I],"Username") == 0 )
		{
			if ( SteamUserName ) { delete[] SteamUserName; } SteamUserName = BuildString(1,Variables[I+1]);
		}
		else if ( _stricmp(Variables[I],"WorkingDir") == 0 )
		{

		}
		else if ( _stricmp(Variables[I],"SDKCallback") == 0 )
		{
			SDKCallback001	=	(MaxsiDistributionClass001*)Variables[I+1];
		}
	}

	m_Initialized		=	true;
	return true;
}

//=============================================================================
//	bool	UpdateProduct()
//
//	Connects, if possible, to a content server and checks if the current version
//	of this product is up to date. If it's not, the thread exits and this function
//	returns false. If it's safe to launch the product the function returns true.
//=============================================================================

int		MaxsiDistributionInterface::UpdateProduct()
{

	//=============================================================================
	// Forward any of these functions to this Interface!
	//=============================================================================

	ErrorFunc		=	(type_ErrorFunc)		&Interface_ReportError;
	InfoFunc		=	(type_InfoFunc)			&Interface_Info;
	NewsUpdatedFunc	=	(type_NewsUpdatedFunc)	&Interface_NewsUpdated;
	StatusFunc		=	(type_StatusFunc)		&Interface_SetStatus;
	SubStatusFunc	=	(type_SubStatusFunc)	&Interface_SetSubStatus;
	ProgressFunc	=	(type_ProgressFunc)		&Interface_SetProgress;
	CheckBlockStates=	(type_CheckBlockStates)	&CheckBlockStatesFast;
	DownloadFunc	=	(type_DownloadFunc)		&Interface_DoDownload;
	NoInternet		=	(type_NoInternet)		&Interface_NoInternet;
	NeedsUpdating	=	(type_NeedsUpdating)	&Interface_NeedsUpdating;
	DownloadNews	=	(type_DownloadNews)		&Interface_DownloadNews;

	//=============================================================================
	// Connect to the Master Content Server and get information about the product!
	//=============================================================================

	//// Spawn the initializer thread
	//HANDLE	hInitialize		=	ME_CreateThread(ThreadInitialize,NULL);

	//// Did everything go well?
	//if ( hInitialize == NULL ) { return true; }

	//// Run the thread!
	//SendMessage(hInitialize,WM_COMMAND,0,0);

	//// Wait for the thread to finish!
	//// TODO: Can this cause a system deadlock? 
	//// <http://msdn.microsoft.com/en-us/library/ms687032%28VS.85%29.aspx>
	//WaitForSingleObject(hInitialize,INFINITE);

	InitializeProduct();

	// Launch the product, even if the Master Content Server doesn't support it.
	if ( Supported == false ) { return true; }

	//=============================================================================
	// Connect to the Master Content Server and detect if the product needs updating!
	//=============================================================================

	//// Spawn the initializer thread
	//HANDLE	hInstall		=	ME_CreateThread(ThreadInstall,NULL);

	//// Did everything go well?
	//if ( hInstall == NULL ) { return true; }

	//// Run the thread!
	//SendMessage(hInstall,WM_COMMAND,0,0);

	//// Wait for the thread to finish!
	//// TODO: Can this cause a system deadlock? 
	//// <http://msdn.microsoft.com/en-us/library/ms687032%28VS.85%29.aspx>
	//WaitForSingleObject(hInstall,INFINITE);

	InstallProduct();

	// And finally - decide our fate!
	if ( MayLaunchProduct )
	{
		return RESULT_RUN;
	}
	else
	{
		return RESULT_DONT_RUN;
	}
}

//=============================================================================
//	bool	ReportCrashes()
//
//	Scans for crash minidumps (.mdmp's) related to this product and uploads
//	any new crashes to a content server.
//=============================================================================

bool	MaxsiDistributionInterface::ReportCrashes()
{
	return true;
}

//=============================================================================
//	bool	IsInitialized()
//
//	Returns true if ->Initialize() has already been run. Returns false if it
//	haven't and should be run.
//=============================================================================

bool	MaxsiDistributionInterface::IsInitialized()
{
	return	m_Initialized;
}

//=============================================================================
//	bool	IsDisabled()
//
//	Returns true if Maxsi Distribution is disabled. (Meaning that Maxsi
//	Distribution may not access the Internet - all other Maxsi Distribution
//	features are running).
//=============================================================================

bool	MaxsiDistributionInterface::IsDisabled()
{
	return	!m_IsEnabled;
}

//=============================================================================
//	bool	IsEnabled()
//
//	Returns true if Maxsi Distribution is enabled.  (Meaning that Maxsi
//	Distribution may  access the Internet).
//=============================================================================

bool	MaxsiDistributionInterface::IsEnabled()
{
	return	m_IsEnabled;
}

//=============================================================================
//	bool	Disable()
//
//	Disables Maxsi Distribution (prevents Maxsi Distribution from accessing
//	the Internet).
//=============================================================================

bool	MaxsiDistributionInterface::Disable()
{
	m_IsEnabled	=	false;
	return true;
}

//=============================================================================
//	bool	Enable()
//
//	Enables Maxsi Distribution (allows Maxsi Distribution to access	the
//	Internet).
//=============================================================================

bool	MaxsiDistributionInterface::Enable()
{
	m_IsEnabled	=	true;
	return true;
}

//=============================================================================
//	bool	CreateSession();
//
//	Terminates all data belonging to previous sessions and creates a new default
//	session. A ses
//=============================================================================

bool	MaxsiDistributionInterface::CreateSession()
{
	return false;
}

//=============================================================================
//	bool	SaveSession(char** OutBuffer, size_t* OutBufferLength);
//
//	Exports a buffer with all the session-data this module needs to store
//	permanently for this session specificly. The application should take care
//	of storing this and passing it onto RestoreSession() when the session is
//	restored. OutBuffer points to a	char* which will be changed to point to a
//	buffer containing OutBufferLength bytes that should be saved. Call
//	SavedSession() when done with the buffer.
//=============================================================================

bool	MaxsiDistributionInterface::SaveSession(char** OutBuffer, size_t* OutBufferLength)
{
	return false;
}

//=============================================================================
//	bool	SavedSession(char* OutBuffer, size_t OutBufferLength);
//
//	Deletes the buffer allocated for use by the application when SaveSession()
//	is called. You must call SavedSession() when done with the buffer.
//=============================================================================

bool	MaxsiDistributionInterface::SavedSession(char* OutBuffer, size_t OutBufferLength)
{
	return false;
}

//=============================================================================
//	bool	RestoreSession(char* OutBuffer, size_t OutBufferLength);
//
//	Restores a previous session.
//=============================================================================

bool	MaxsiDistributionInterface::RestoreSession(char* Buffer, size_t BufferLength)
{
	return false;
}

//=============================================================================
//	bool	RegisterModule(MaxsiDistributionModule* Module);
//
//	Module is added to the array of MD-extension modules accessed with the
//	MaxsiDistributionModule interface.
//=============================================================================

bool	MaxsiDistributionInterface::RegisterModule(MaxsiDistributionModule001* Module)
{
	if (!Module) { return false; }
	return Module->SetMaxsiDistributionInterface(this);
}

//=============================================================================
//	bool	SDKMsg(char* Message);
//
//	Sends a message to the client app console.
//=============================================================================

bool	MaxsiDistributionInterface::SDKMsg(char* Message)
{
	return SDKCallback->IngameMsg(Message);
}

//=============================================================================
//	bool	SDKMsgDebug(char* Message);
//
//	Sends a message to the client app console if debug information is enabled
//	in the SDK.
//=============================================================================

bool	MaxsiDistributionInterface::SDKMsgDebug(char* Message)
{
	return SDKCallback->IngameMsgDebug(Message);
}